const { v4 } = require('uuid');
const { Result } = require("@/libs/result");
const userModel = require("./user.model");
const arrayUtil = require("@/utils/array.util");
const CommonService = require('@/common/common.service');
const fileBusinessService = require('@/common/file-business.service');
const WxApiService = require('@/common/services/wx-api.service');
const AesSecurity = require('@/security/aes.security');
const redisClient = require("@/redis/redis-client");
const RedisKeysConstant = require('@/constants/redis-keys.constant');
const { RedisClient } = require('redis');
const { commonService } = require('../../common/file-business.service');
const { TenantContext } = require('@/core/tenant-context');

/**
 * 用户服务
 */
class UserService {
    commonService = new CommonService();
    aesSecurity = new AesSecurity();

    /**
     * 查询用户列表
     */
    async queryUserList({ keyword, page, page_size }) {
        try {
            const queryResult = await userModel.queryUserList({ keyword, page, page_size: page_size });
            const totalResult = await userModel.queryUserListTotal({ keyword });
            if (queryResult.code === 200) {
                let userList = queryResult.results;
                userList = await fileBusinessService.setBusinessRowsFile({ rows: userList, businessIdFiled: 'avatar', fileKey: 'avatar' })
                userList = userList.map(user => {
                    if (Array.isArray(user.avatar)) {
                        user.avatar = user.avatar[0];
                    }
                    return user;
                });
                return Result.Paging(page, totalResult.results[0].count, queryResult.results);
            }
            return Result.Failed('查询用户列表失败')
        } catch (error) {
            console.log('用户列表查询失败：', error.message)
            return Result.Failed('查询用户列表失败')
        }
    }

    /**
     * 创建用户
     * @param {*} data 
     * @param {*} param1 
     */
    async createUser(data, { tid, user }) {
        try {
            console.log(data);
            const avatar = data.user_type ? v4() : null;

            // 先创建用户信息
            const [_userError, userResult] = await userModel.createUser({
                username: data.username,
                password: data.password,
                name: data.name,
                phone: data.phone,
                gender: data.gender,
                user_type: data.user_type,
                avatar: avatar
            });
            if (_userError) {
                return Result.Failed('用户创建失败');
            }

            // 设置头像
            if (avatar) {
                await fileBusinessService.bindingFiles({ business_id: avatar, files: data.avatar, business_type: 'system.user_avatar' })
            }

            // 同步到租户中
            const [_tenantError] = await userModel.createTenantUser({
                user_id: userResult.id,
                role_code: 'staff'
            });
            if (_tenantError) {
                return Result.Failed('用户创建失败');
            }

            // 如果为员工用户
            if (data.user_type === 3) {
                const [_staffError, staffResult] = await userModel.createStaff({
                    user_id: userResult.id,
                    employee_no: data.employee_no,
                    name: userResult.name,
                    position: data.position,
                    hire_date: data.hire_date,
                    id_card: data.id_card,
                    address: data.address,
                    emergency_contact: data.emergency_contact,
                    emergency_phone: data.emergency_phone,
                    education: data.education,
                    bank_card: data.bank_card,
                    bank_name: data.bank_name,
                    remark: data.remark
                })
            }
            return Result.Success(userResult);
        } catch (error) {
            console.log("创建用户错误：", error);
            return Result.Failed('用户创建失败');
        }
    }

    /**
     * 创建店铺
     * @param {*} data 
     */
    async createShop(data) {
        try {
            const [error, result] = await userModel.createShop({
                shop_code: data.shop_code || '',
                shop_name: data.shop_name || '',
                address: data.address || '',
                contact_phone: data.contact_phone || '',
            })
            if (error) {
                return Result.Failed('创建失败');
            }
            return Result.Success(result);
        } catch (error) {
            console.log('创建店铺失败：', error);
            return Result.Failed('创建失败');
        }
    }

    /**
     * 修改店铺
     * @param {*} data 
     */
    async updateShop(id, data) {
        try {
            const [error, result] = await userModel.updateShop(id, {
                shop_name: data.shop_name || '',
                address: data.address || '',
                contact_phone: data.contact_phone || '',
            })
            if (error) {
                return Result.Failed('修改失败');
            }
            return Result.Success(result);
        } catch (error) {
            console.log('创建店铺失败：', error);
            return Result.Failed('修改失败');
        }
    }

    /**
     * 查询租户列表
     * @returns 
     */
    async queryTenants() {
        try {
            const user_id = TenantContext.getCurrentUser();
            if (!user_id) {
                return Result.Failed('查询失败')
            }
            const result = await userModel.queryTenantListByUserId({ user_id: user_id });
            if (result.code !== 200) {
                 return Result.Failed('查询失败')
            }
            return Result.Success(result.results);
        } catch (error) {
            console.log(error.message);
            return Result.Failed('查询失败')
        }
    }

    /**
     * 设置用户租户
     * @param {*} param0 
     * @param {*} data 
     * @returns 
     */
    async setUserTenant({ user_id }, body) {
        try {
            const [error, data] = await userModel.setUserTenants({
                tenants: body.tenants || [],
                uid: user_id,
                role_code: body.role_code || 'system_super_admin'
            });
            if (error) {
                console.log('设置用户租户失败！');
                return Result.Failed('设置用户租户失败')
            }
            return Result.Success(data);
        } catch (error) {
            console.log('设置用户租户失败！');
            return Result.Failed('设置用户租户失败')
        }
    }


    /**
     * 创建分组
     * @param {*} param0 
     * @param {*} param1 
     */
    async createFamilyGroup({ name, members }, { user }) {
        try {
            if (name.length > 50) {
                return Result.Failed('分组名称应该小于50个字符');
            }
            // 验证重复
            const checkResult = await userModel.checkGroupNameExist({ name, uid: user.uid });
            if (checkResult.code !== 200 || checkResult.results.length > 0) {
                return Result.Failed('分组名称已存在');
            }
            // // 写入数据
            const id = v4();
            const result = await userModel.createFamilyGroup({ id, name, uid: user.uid })
            if (result.code !== 200) {
                return Result.Failed('创建失败');
            }
            // 如果有成员，绑定成员
            members = members || [user.uid]
            if (Array.isArray(members) && members.length > 0) {
                members = [...new Set([...members, user.uid])]
                const insertResult = await userModel.createFamilyGroupMembers({ gid: id, members });
                if (insertResult.code !== 200) {
                    return Result.Failed('创建失败');
                }
            }
            return Result.Success();
        } catch (error) {
            console.log('创建分组失败：', error);
            return Result.Failed(error);
        }
    }

    /**
     * 删除家庭组
     * @param {*} id 
     * @param {*} param1 
     * @returns 
     */
    async deleteFamilyGroup(id, { gid, user }) {
        try {
            const isLock = await this.commonService.checkRowLocked('family_group', id, 'id');
            if (isLock) {
                return Result.Failed('当前家庭组正在使用中，无法删除');
            }
            const groupResult = await userModel.getFamilyGroupById(id);
            if (groupResult.code === 200 && groupResult.results.length > 0) {
                const [group] = groupResult.results;
                if (group && group.create_user !== user.uid) {
                    return Result.Failed('删除失败，请创建人进行删除操作');
                }
            } else {
                return Result.Failed('删除失败');
            }
            const delResult = await userModel.deleteFamilyGroup(id);
            if (delResult.code === 200 && delResult.results.changedRows > 0) {
                return Result.Success();
            }
            return Result.Failed('删除失败');
        } catch (error) {
            console.log('删除分组失败：', error);
            return Result.Failed(error.message);
        }
    }

	/**
	 * 查询用户下的群组列表
	 * @returns
	 */
	async queryGroupList({ id }) {
		try {
			const result = await userModel.queryGroupList(id);
			return Result.Success(result.results);
		} catch (error) {
			return Result.Failed(error);
		}
	}

	/**
	 * 查询分组及成员
	 * @returns
	 */
	async queryGroupMembers() {
		try {
			const result = await userModel.queryGroupMembers(id);
			return Result.Success(result.results);
		} catch (error) {
			return Result.Failed(error);
		}
	}

	/**
	 * 查询分组下的成员列表
	 * @returns
	 */
	async queryGroupMemberList({ gid, user }) {
		try {
            if (!user.uid) {
                return Result.Failed("参数错误");
            }
			const groupResult = await userModel.queryGroupList(user.uid); // 通过用户id查询当前的分组列表
			if (groupResult.code === 200) {
				const groupIds = groupResult.results.map(group => group.id);
                const groupMembersResult = await userModel.queryGroupMembers(groupIds); // 查询父组id下的所有成员
                // 查询家庭成员的头像
                // const avatarFiles = await fileBusinessService.getRowsBusinessFiles(...new Set([groupMembersResult.results.map(member => member.avatar)]))
                const groupMemberList = await fileBusinessService.setBusinessRowsFile({ rows: groupMembersResult.results, fileBizIdKey: 'avatar_image', fileKey: 'avatar_image' });
				const membersGroupData = arrayUtil.groupBy(groupMemberList, "group_id"); // 通过分组id分组
				const results = groupResult.results;
				for (let i = 0; i < groupIds.length; i++) {
					const id = groupIds[i];
                    const groupItem = results[i];
                    // 给每个分组添加成员信息
					if (membersGroupData[id]) {
						groupItem.members = membersGroupData[id].map(member => {
                            if (Array.isArray(member.avatar_image) && member.avatar_image.length > 0) {
                                member.path = member.avatar_image[0].previewPath;
                            }
                            return member;
						});
					}
				}
				return Result.Success(results);
			}
		} catch (error) {
			return Result.Failed(error);
		}
	}

    /**
     * 设置头像昵称
     * @param {*} param0 
     */
    async setAvatarName({ avatar, nickName }, { gid, user }) {
        try {
            const avatarId = v4();
            if (avatar) {
                await fileBusinessService.bidBizFile({
                    id: v4(),
                    fileId: avatar,
                    bizId: avatarId,
                    createUser: user.uid,
                    gid: gid
                });
                await this.commonService.setRowLocked('file_files', avatar, 'id'); // 锁定行
            }
            const updateResult = await userModel.setAvatarNickName({
                avatar: avatar ? avatarId : null,
                nickName: nickName,
                openid: user.openid
            });
            if (updateResult.code === 200 && updateResult.results.changedRows > 0) {
                return Result.Success()
            } else {
                return Result.Failed('修改失败');
            }
        } catch (error) {
            return Result.Failed(error);
        }
    }

    /**
     * 家庭扫码加入
     * @param {*} param0 
     */
    async familyScanJoin({ uid, sign }) {
        try {

            const access_token = await WxApiService.getAccessToken();
            const code = await WxApiService.getWxACode();
            let cacheData = await redisClient.get(RedisKeysConstant.familyScanSign(sign));
            cacheData = (cacheData && cacheData.data) ? this.aesSecurity.decrypt(cacheData.data) : null
            if (!cacheData) {
                return Result.Failed('无效签名');
            }
            cacheData = JSON.parse(cacheData); // 转为json对象
            // 判断有效期
            if (cacheData.t < Date.now()) {
                await redisClient.del(RedisKeysConstant.familyScanSign(sign)); // 删除过期的数据
                return Result.Failed('签名已过期');
            }
            const { g } = cacheData;
            const checkResult = await userModel.checkFamilyGroupExistById({ gid: g });
            // 验证id是否存在
            if (checkResult.code === 200 && checkResult.results.length > 0) {
                const checkUser = await userModel.checkUserExistById({ uid: uid });
                // 验证用户是否存在
                if (checkUser.code !== 200 || checkUser.results.length === 0) {
                    return Result.Failed('未知用户')
                }
                 // 写入数据
                const joinResult = await userModel.setUserFamilyGroup({ user_id: uid, gid: g });
                if (joinResult.code === 200) {
                    await redisClient.del(RedisKeysConstant.familyScanSign(sign)); // 删除临时签名
                    return Result.Success("家庭加入成功");
                }
            }
            return Result.Failed('操作失败');
        } catch (error) {
            return Result.Failed(error);
        }
    }

    /**
     * 获取扫码加入家庭签名
     * @param {*} param0 
     */
    async getScanFamilySign({ gid, user }) {
        try {
            const code = v4().slice(0, 28).replace(/-/g, "").toUpperCase();
            const signStr = this.aesSecurity.encrypt({
                g: gid,
                u: user.uid,
                c: code,
                t: Date.now() + 60000 * 10 // 有效期10分钟
            });
            await redisClient.set(RedisKeysConstant.familyScanSign(code), {
                create_time: Date.now(),
                data: signStr
            });
            return Result.Success(code);
        } catch (error) {
            console.log(error);
            return Result.Failed(error);
        }
    }

    /**
     * 获取二维码
     * @param {*} body 
     * @param {*} param1 
     */
    async getFamilyScanCode({ url, query }, { gid, user }) {
        try {
            const codeImage = await WxApiService.getWxACode({ url, query });
            if (codeImage) {
                return codeImage
            }
            return Result.Failed('获取二维码失败');
        } catch (error) {
            console.log('获取家庭组二维码失败：', error);
            return Result.Failed(error);
        } 
    }

    /**
     * 创建用户默认家庭组
     * @param {string} uid
     */
    async createUserDefaultFamilyGroup(uid) {
        try {
            const defaultGroupName = '默认家庭组';
            const id = v4();
            // 创建默认家庭组
            const result = await userModel.createFamilyGroup({ id: id, uid: uid, name: defaultGroupName });
            if (result.code === 200) {
                // 将当前用户添加到默认家庭组中
                const addResult = await userModel.createFamilyGroupMembers({
                    gid: id,
                    members: [uid]
                })
                if (addResult.code == 200) {
                    return true;
                }
                return false;
            }
            return false;
        } catch (error) {
            console.log('创建默认家庭组失败：', error);
            return false;
        }
    }

    /**
     * 获取家庭邀请码
     * @description 扫码加入调用的：familyInputJoin 方法进行验证、加入逻辑
     * @param {*} param0 
     * @returns 
     */
    async getFamilyInvitationNumber({ gid, user }) {
        try {
            function generateUnique4DigitNumbers(count) {
                // 创建范围数组
                const numbers = [];
                for (let i = 1000; i <= 9999; i++) {
                  numbers.push(i);
                }
                
                // Fisher-Yates洗牌算法
                for (let i = numbers.length - 1; i > 0; i--) {
                  const j = Math.floor(Math.random() * (i + 1));
                  [numbers[i], numbers[j]] = [numbers[j], numbers[i]];
                }
                
                return numbers.slice(0, count);
            }
            const [code] = generateUnique4DigitNumbers(1);
            const now = Date.now();
            const expired_time = now + (60000 * 10);
            // 同步到redis中
            const [error] = await this._saveFamilyInvitationNumber(code, {
                gid: gid,
                uid: user.uid,
                c_time: now,
                // 有效期5分钟
                expired_time: expired_time,
            });
            if (error) {
                return Result.Failed(error);
            }
            return Result.Success({
                code: code,
                expired_time: expired_time
            });
        } catch (error) {
            console.log('获取家庭邀请码失败：', error);
            return Result.Failed(error);
        }
    }

    /**
     * 输入邀请码加入家庭组
     * @param {*} code 
     * @param {*} param1 
     * @returns 
     */
    async familyInputJoin(code, { gid, user }) {
        try {
            const cacheKey = RedisKeysConstant.familyInvitationNumber(code);
            const redisCacheData = await redisClient.get(RedisKeysConstant.familyInvitationNumber(code));
            // key是否存在有效
            if (!redisCacheData) {
                return Result.Failed('无效的邀请码')
            }
            // 验证是否过期
            if (!redisCacheData.expired_time || redisCacheData.expired_time < Date.now()) {
                await redisClient.del(cacheKey);
                return Result.Failed('邀请码已过期');
            }
            if (gid) {
                // 判断当前用户是否在xxx家庭中，在则不允许加入
                const queryResult = await userModel.getFamilyIdListByUserId({ uid: user.uid });
                if (queryResult.code === 200 && queryResult.results.length > 0) {
                    const queryIdList = queryResult.results.map(g => g.group_id);
                    if (queryIdList.includes(redisCacheData.gid)) {
                        return Result.Failed('当前用户已加入该家庭组');
                    }
                }
                const joinResult = await userModel.setUserFamilyGroup({ user_id: user.uid, gid: redisCacheData.gid });
                await this.commonService.setRowLocked('family_group', gid, 'id'); // 加锁状态
                if (joinResult.code === 200) {
                    return Result.Success();
                }
                return Result.Failed('家庭组加入失败');
            }
            return Result.Failed('家庭组加入失败');
        } catch (error) {
            console.log('获取家庭邀请码失败：', error);
            return Result.Failed(error);
        }
    }

    /**
     * 存储家庭码
     * @param {*} code 
     * @param {*} data 
     * @returns 
     */
    _saveFamilyInvitationNumber(code, data) {
        return new Promise(async resolve => {
            const setError = (message) => {
                resolve([message, null]);
            }
            try {
                const cacheKey = RedisKeysConstant.familyInvitationNumber(code);
                // 取出redis中所有keys
                let cacheKeys = await redisClient.get(RedisKeysConstant.familyInvitationNumberKeys);
                if (!cacheKeys || !Array.isArray(cacheKeys)) {
                    cacheKeys = [];
                }
                // 验证重复
                if (cacheKeys.includes(code)) {
                    setError('生成的邀请码重复');
                    return;
                }
                cacheKeys.push(code);
                await redisClient.set(cacheKey, data);
                await redisClient.set(RedisKeysConstant.familyInvitationNumberKeys, cacheKeys);
                return resolve([null, {
                    keys: cacheKeys
                }]);
            } catch (error) {
                setError(error)
            }
        })
    }
}

module.exports = new UserService();
